/**
 * 
 */
package World;

/**
 * @author kreso
 *
 */
public class Kromosom {
	private String bits;
	private double fitness;
	
	
	/**
	 * @return the bits
	 */
	public String getBits() {
		return bits;
	}
	/**
	 * @param bits the bits to set
	 */
	public void setBits(String bits) {
		this.bits = bits;
	}
	/**
	 * @return the fitness
	 */
	public double getFitness() {
		return fitness;
	}
	/**
	 * @param fitness the fitness to set
	 */
	public void setFitness(double fitness) {
		this.fitness = fitness;
	}
	
	
	/**
	 * Function calculates fitness for this Kromosom
	 * @param target - targeted number
	 */
	public void AssignFitness(double target) {
		
		//holds decimal values of gene sequence
		int[] dec_val = new int[(int)Uvjeti.CHROMO_LENGTH/Uvjeti.GENE_LENGTH];
	    int num_elements = ParseBits(dec_val);
	    //System.out.println(Arrays.toString(dec_val));
	    
		// ok, we have a buffer filled with valid values of: operator - number - operator - number..
		// now we calculate what this represents.
		double result = 0.0f;
		for (int i=0; i < num_elements-1; i+=2)
		{
			switch (dec_val[i])
			{
				case 10:
					result += dec_val[i+1];
					break;

				case 11:
					result -= dec_val[i+1];
					break;

				case 12:
					result *= dec_val[i+1];
					break;

				case 13:
					result /= dec_val[i+1];
					break;

			}//end switch

			
		}
		
//		for (int i=0; i < num_elements; i++){
//			PrintGeneSymbol(dec_val[i]);
//		}
//		System.out.println();
//		System.out.println(result);
		
		
		// Now we calculate the fitness. First check to see if a solution has been found
		// and assign an arbitarily high fitness score if this is so.
		if (Math.abs(target- result) < 0.001) // percision - 10^-3
			setFitness(999.0f);

		else
			setFitness( 1/(double)Math.abs((double)(target - result)) );
		return;
	}

	
	/**
	 * Given a chromosome this function will step through the genes one at a time and insert
	// the decimal values of each gene (which follow the operator -> number -> operator rule)
	// into a buffer.
	 * 
	 * @param dec_val - buffer array of decimal values
	 * @return - Returns the number of elements in the buffer
	 */
	public int ParseBits(int[] dec_val) {
		
		//counter for buffer position
		int cBuff = 0;

		// step through bits a gene at a time until end and store decimal values
		// of valid operators and numbers. Don't forget we are looking for operator -
		// number - operator - number and so on... We ignore the unused genes 1111
		// and 1110

		//flag to determine if we are looking for an operator or a number
		boolean bOperator = true;

		//storage for decimal value of currently tested gene
		int this_gene = 0;

		for (int i = 0; i < Uvjeti.CHROMO_LENGTH; i += Uvjeti.GENE_LENGTH) {
			//convert the current gene to decimal
	        this_gene = Integer.parseInt(bits.substring(i, i + Uvjeti.GENE_LENGTH), 2);
	        //System.out.println(bits.substring(i, i + Uvjeti.GENE_LENGTH));

			//find a gene which represents an operator
			if(bOperator) {
				if ( (this_gene < 10) || (this_gene > 13) )
					continue;

				else {
					bOperator = false;
					dec_val[cBuff++] = this_gene;
					continue;
				}
			}

			//find a gene which represents a number
			else {
				if (this_gene > 9)
					continue;

				else {
					bOperator = true;
					dec_val[cBuff++] = this_gene;
					continue;
				}
			}

		}//next gene

		//	now we have to run through buffer to see if a possible divide by zero
		//	is included and delete it. (ie a '/' followed by a '0'). We take an easy
		//	way out here and just change the '/' to a '+'. This will not effect the
		//	evolution of the solution
	    for (int i = 0; i < cBuff; i++) {
			if ( (dec_val[i] == 13) && (dec_val[i+1] == 0) )

				dec_val[i] = 10;
		}

		return cBuff;
	}
}
